package com.client.buttlefield.ui;

import java.util.Vector;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.builders.ColorAdjustBuilder;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeType;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Buttlefield extends Application{

	static Buttlefield buttle = null;
	Group root;
	Rectangle screenBounds;
	
	GlassPane glassPane;
	Rebounder rebounder ;
	
	private Vector<ButtleListener> buttlelisteners = new Vector<ButtleListener>();

    public void addButtleListener(ButtleListener btl ) {
        
        if (buttlelisteners.contains(btl ))
            return;
        buttlelisteners.addElement(btl);
      
    }
    
    public void removeButtleListener(ButtleListener l ) {
    	buttlelisteners.remove( l );
    }
	
	public static Buttlefield createButtle(){
		
		try {
			if (buttle == null) {			  
			    Application.launch (Buttlefield.class, null);			
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return buttle;
	}
	
	public class Rebounder {
		Rectangle lasso;
	    double px;
	    double py;
	    
	    Rebounder() {
	      lasso = new Rectangle(0, 0);
	      lasso.setFill(Color.TRANSPARENT);
	      lasso.setSmooth(false);
	      lasso.setStroke(Color.RED);
	      lasso.setStrokeWidth(1);
	      lasso.setStrokeType(StrokeType.OUTSIDE);
	      lasso.setMouseTransparent(true);
	      lasso.setVisible(false);
	    }

	    Rectangle start(double x, double y) {
	      lasso.setX(x);
	      lasso.setY(y);
	      lasso.setWidth(0);
	      lasso.setHeight(0);
	      px = x;
	      py = y;
	      lasso.setVisible(true);
	      return lasso;
	    }

	    Rectangle rebound(double x, double y) {
	      lasso.setWidth(Math.abs(x - px));
	      lasso.setHeight(Math.abs(y - py));
	      lasso.setX(Math.min(x, px));
	      lasso.setY(Math.min(y, py));
	      return lasso;
	    }

	    Rectangle stop(double x, double y) {
	      rebound(x, y);
	      lasso.setVisible(false);
	      return lasso;
	    }

	    boolean isStopped() { return !lasso.isVisible(); }

	    Node getLasso() { return lasso; }

	    Shape shapeBuilder(Rectangle r) {
	      return r != null
	        ? Path.intersect(screenBounds, r)
	        : new Rectangle(0, 0);//screenBounds.getWidth(), screenBounds.getHeight());
	    }
	}
	
	class KeyPane extends Group {
	     public KeyPane(final Stage stage){
	       final Rectangle keyEventPane =
	         new Rectangle(screenBounds.getWidth(), screenBounds.getHeight());
	       keyEventPane.setFill(Color.TRANSPARENT);
	       keyEventPane.setStroke(null);
	       keyEventPane.setMouseTransparent(true);
	       keyEventPane.setFocusTraversable(true); // for keyPressed events
	       
	       keyEventPane.setOnKeyPressed(new EventHandler<KeyEvent>() {
	         @Override 
	         public void handle(KeyEvent key) {
	           if (key.getCode() == KeyCode.ESCAPE) {
	             stage.setVisible(false); // == Close
	           } else if (key.getCode() == KeyCode.A) {
	        	  // getActiveChild(new Rectangle(screenBounds.getWidth()+1, 
	        			  // screenBounds.getHeight()+1));
	           }
	         }
	       });
	       getChildren().add (keyEventPane);
	     }
	   }
	
	class GlassPane extends Group {
	     void setShape(Shape shape) {
	       while (!getChildren().isEmpty()) {
	         getChildren().remove(0);
	       }
	       if ( shape != null ) {
	    	   shape.setFill(new Color(0.1, 0.2, 0.3, 0.4));
	         shape.setMouseTransparent(true);
	         shape.setStroke(null);
	         getChildren().add(shape);
	       }
	     }
	   }
	@Override
	public void start(Stage stage) throws Exception {

	     root = new Group();
	     Scene scene = new Scene(root, 600, 400);
	     scene.setFill(Color.LIGHTGRAY);
	     scene.setCursor(Cursor.CROSSHAIR);
	     
	     scene.setOnMousePressed(new EventHandler<MouseEvent>() {
	         @Override public void handle(MouseEvent me) {

				if(me.getButton() == MouseButton.PRIMARY){

					switch (me.getClickCount()) {
					case 1:{
				           glassPane.setShape(
				  	             rebounder.shapeBuilder(rebounder.start(me.getX(), me.getY())));
						}						
						break;
					case 2:
						if (activeParticipant != null) {
							int x = (int)me.getX();
							int y = (int)me.getY();
							
							fireDataAvaliableEvent(x, y, 5, activeParticipant.getIdent());							
							//activeParticipant.moving(x, y, 5);
						}
						
						break;
					default:
						break;
					}
				}
	         }
	       });

	     scene.setOnMouseDragged(new EventHandler<MouseEvent>(){

				@Override
				public void handle(MouseEvent me) {
					 glassPane.setShape(
				     rebounder.shapeBuilder(rebounder.rebound(me.getX()+1, me.getY()+1)));
				}
	       });

	     scene.setOnMouseReleased(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent me) {
				 if ( !rebounder.isStopped() ) {
					 getActiveChild(rebounder.stop(me.getX()+1, me.getY()+1));
			}}
	       });
	     
	     stage.initStyle(StageStyle.TRANSPARENT);
	     //stage.setFullScreen(true);
	     stage.setScene(scene);
	     stage.setVisible(true);

	     screenBounds = new Rectangle (
	       Screen.getPrimary().getBounds().getWidth(),
	       Screen.getPrimary().getBounds().getHeight()
	     );
	     rebounder = new Rebounder();
	     KeyPane keyPane = new KeyPane(stage);//, rebounder = new Rebounder());
	     glassPane = new GlassPane();
	     glassPane.setShape(rebounder.shapeBuilder(null)); 

	     root.getChildren().addAll(new Node[] {keyPane, glassPane, rebounder.getLasso()});
	     
	     buttle = this;
	}

	Vector<Participant> activecircle = new Vector<Participant>();
	Participant activeParticipant;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		 Application.launch(args);
	
	}

	private void getActiveChild(final Rectangle stop) {

		final ColorAdjust effectPressed
		  		= new ColorAdjustBuilder().brightness(-0.5).build();
		
		for (Participant p : activecircle) {
				if(stop.contains(p.getCenterX(), p.getCenterY())){
					p.setEffect(effectPressed );
					activeParticipant = p;
					System.out.println("color was called");
			}
		}
		
		glassPane.setShape(rebounder.shapeBuilder(null));
	}
	
	public void addParticipant(final Participant c, final Boolean active) {
		 try {
			 Platform.runLater(new Runnable() { 
		            @Override
		            public void run() {
		            	root.getChildren().add(c);
		            	if(active)
		            		activecircle.add(c);
		            }
		        });
			
		}catch (Exception e) {
			e.printStackTrace();
		}
	}


	protected void fireDataAvaliableEvent(int x, int y, int t, int id){
		
        ButtleEvent ev = new ButtleEvent(activeParticipant, x, y, t, id);
        
        for (ButtleListener listener : buttlelisteners){
          listener.FireMove(ev);
        }
      }
}
